package com.zhpan.indicator.drawer;

import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

import com.zhpan.indicator.enums.IndicatorSlideMode;
import com.zhpan.indicator.options.IndicatorOptions;
import com.zhpan.indicator.utils.ArgbEvaluator;
import com.zhpan.indicator.utils.IndicatorUtils;

/**
 * 矩形
 *
 * @since 2021-04-13
 */
public class RectDrawer extends BaseDrawer {
    protected final RectFloat mRectF = new RectFloat();

    /**
     * 根据配置矩形
     *
     * @param options 配置
     */
    public RectDrawer(IndicatorOptions options) {
        super(options);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        int pageSize = mOptions.getPageSize();
        if (pageSize > 1) {
            int slideMode = mOptions.getSlideMode();

            if (isWidthEquals() && slideMode != IndicatorSlideMode.NORMAL) {
                drawUncheckedSlider(canvas, pageSize);
                drawCheckedSlider(canvas);
            } else {
                if (slideMode == IndicatorSlideMode.SCALE) {
                    for (int i = 0; i < pageSize; i++) {
                        drawScaleSlider(canvas, i);
                    }
                } else {
                    drawInequalitySlider(canvas, pageSize);
                }
            }
        }
    }

    /**
     * 绘制动画
     *
     * @param canvas 画布
     */
    protected void drawDash(Canvas canvas) {
        // do noting
    }

    private void drawScaleSlider(Canvas canvas, int index) {
        float indicatorGap = mOptions.getSliderGap();
        float sliderHeight = mOptions.getSliderHeight();
        int currentPosition = mOptions.getCurrentPosition();

        float normalWidth = mOptions.getNormalSliderWidth();
        float checkedWidth = mOptions.getCheckedSliderWidth();

        if (mOptions.getSlideProgress() == 1.0) {
            mOptions.setSlideProgress(0.999f);
        }

        Color checkedColor = mOptions.getCheckedSliderColor();
        Color normaColor = mOptions.getNormalSliderColor();
        if (index < currentPosition) {
            mPaint.setColor(normaColor);
            float left;
            if (currentPosition == mOptions.getPageSize() - 1) {
                left = (index * normalWidth + index * indicatorGap) + (checkedWidth - normalWidth) * mOptions.getSlideProgress();
            } else {
                left = index * normalWidth + index * indicatorGap;
            }
            mRectF.modify(left, 0f, left + normalWidth, sliderHeight);
            drawRoundRect(canvas, sliderHeight, sliderHeight);
        } else if (index == currentPosition) {
            mPaint.setColor(checkedColor);
            float slideProgress = mOptions.getSlideProgress();
            if (currentPosition == mOptions.getPageSize() - 1) {
                int evaluate = (int) ArgbEvaluator.evaluate(slideProgress, checkedColor.getValue(), normaColor.getValue());
                mPaint.setColor(new Color(evaluate));
                float right = (mOptions.getPageSize() - 1) * (normalWidth + mOptions.getSliderGap()) + checkedWidth;
                float left = right - checkedWidth + (checkedWidth - normalWidth) * slideProgress;
                mRectF.modify(left, 0f, right, sliderHeight);
                drawRoundRect(canvas, sliderHeight, sliderHeight);
            } else {
                if (slideProgress < 1) {
                    int evaluate = (int) ArgbEvaluator.evaluate(slideProgress, checkedColor.getValue(), normaColor.getValue());
                    mPaint.setColor(new Color(evaluate));
                    float left = index * normalWidth + index * indicatorGap;
                    float right = left + normalWidth + (checkedWidth - normalWidth) * (1 - slideProgress);
                    mRectF.modify(left, 0f, right, sliderHeight);
                    drawRoundRect(canvas, sliderHeight, sliderHeight);
                }
            }

            if (currentPosition == mOptions.getPageSize() - 1) {
                if (slideProgress > 0) {
                    int evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress, checkedColor.getValue(), normaColor.getValue());
                    mPaint.setColor(new Color(evaluate));
                    float left = 0f;
                    float right = left + normalWidth + (checkedWidth - normalWidth) * slideProgress;
                    mRectF.modify(left, 0f, right, sliderHeight);
                    drawRoundRect(canvas, sliderHeight, sliderHeight);
                }
            } else {
                if (slideProgress > 0) {
                    int evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress, checkedColor.getValue(), normaColor.getValue());
                    mPaint.setColor(new Color(evaluate));
                    float right = index * normalWidth + index * indicatorGap + normalWidth + (indicatorGap + checkedWidth);
                    float left = right - normalWidth - (checkedWidth - normalWidth) * slideProgress;
                    mRectF.modify(left, 0f, right, sliderHeight);
                    drawRoundRect(canvas, sliderHeight, sliderHeight);
                }
            }
        } else {
            if (currentPosition + 1 != index || mOptions.getSlideProgress() == 0f) {
                mPaint.setColor(normaColor);
                float left = index * minWidth + index * indicatorGap + (checkedWidth - minWidth);
                mRectF.modify(left, 0f, left + minWidth, sliderHeight);
                drawRoundRect(canvas, sliderHeight, sliderHeight);
            }
        }
    }

    /**
     * 绘制圆角矩形
     *
     * @param canvas 画布
     * @param height 高度
     * @param height1 宽度
     */
    protected void drawRoundRect(Canvas canvas, float height, float height1) {
        drawDash(canvas);
    }

    private void drawCheckedSlider(Canvas canvas) {
        mPaint.setColor(mOptions.getCheckedSliderColor());
        int slideMode = mOptions.getSlideMode();
        switch (slideMode) {
            case IndicatorSlideMode.SMOOTH:
                drawSmoothSlider(canvas);
                break;
            case IndicatorSlideMode.WORM:
                drawWormSlider(canvas);
                break;
            case IndicatorSlideMode.COLOR:
                drawColorSlider(canvas);
                break;
            default:
        }
    }

    private void drawColorSlider(Canvas canvas) {
        int currentPosition = mOptions.getCurrentPosition();
        float slideProgress = mOptions.getSlideProgress();
        float left = currentPosition * minWidth + currentPosition * mOptions.getSliderGap();
        if (slideProgress < 0.99) {
            int evaluate = (int) ArgbEvaluator.evaluate(slideProgress, mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
            mPaint.setColor(new Color(evaluate));
            mRectF.modify(left, 0f, left + minWidth, mOptions.getSliderHeight());
            drawRoundRect(canvas, mOptions.getSliderHeight(), mOptions.getSliderHeight());
        }

        float nextSliderLeft = left + mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
        if (currentPosition == mOptions.getPageSize() - 1) {
            nextSliderLeft = 0f;
        }
        int evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress, mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
        mPaint.setColor(new Color(evaluate));
        mRectF.modify(nextSliderLeft, 0f, nextSliderLeft + minWidth, mOptions.getSliderHeight());
        drawRoundRect(canvas, mOptions.getSliderHeight(), mOptions.getSliderHeight());
    }

    private void drawWormSlider(Canvas canvas) {
        float sliderHeight = mOptions.getSliderHeight();
        float slideProgress = mOptions.getSlideProgress();
        int currentPosition = mOptions.getCurrentPosition();
        float distance = mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
        float startCoordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, currentPosition);
        float left = startCoordinateX + coerceAtLeast(distance * (slideProgress - 0.5f) * 2.0f, 0f) - mOptions.getNormalSliderWidth() / 2;
        float right = startCoordinateX + coerceAtMost(distance * slideProgress * 2f, distance)
            + mOptions.getNormalSliderWidth() / 2;
        mRectF.modify(left, 0f, right, sliderHeight);
        drawRoundRect(canvas, sliderHeight, sliderHeight);
    }

    private void drawSmoothSlider(Canvas canvas) {
        float currentPosition = mOptions.getCurrentPosition();
        float indicatorGap = mOptions.getSliderGap();
        float sliderHeight = mOptions.getSliderHeight();
        float left = currentPosition * maxWidth + currentPosition * +indicatorGap
            + (maxWidth + indicatorGap) * mOptions.getSlideProgress();
        mRectF.modify(left, 0f, left + maxWidth, sliderHeight);
        drawRoundRect(canvas, sliderHeight, sliderHeight);
    }

    private void drawUncheckedSlider(Canvas canvas, int pageSize) {
        for (int i = 0; i < pageSize; i++) {
            mPaint.setColor(mOptions.getNormalSliderColor());
            float left = i * maxWidth + i * +mOptions.getSliderGap() + (maxWidth - minWidth);
            mRectF.modify(left, 0f, left + minWidth, mOptions.getSliderHeight());
            drawRoundRect(canvas, mOptions.getSliderHeight(), mOptions.getSliderHeight());
        }
    }

    private void drawInequalitySlider(Canvas canvas, int pageSize) {
        float left = 0f;
        float sliderWidth;
        int currentPosition = mOptions.getRealPosition();
        Color checkedSliderColor = mOptions.getCheckedSliderColor();
        Color normalSliderColor = mOptions.getNormalSliderColor();
        float sliderHeight = mOptions.getSliderHeight();
        for (int i = 0; i < pageSize; i++) {
            sliderWidth = currentPosition == i ? maxWidth : minWidth;
            Color color = i == currentPosition ? checkedSliderColor : normalSliderColor;
            mPaint.setColor(color);
            mRectF.modify(left, 0f, left + sliderWidth, mOptions.getSliderHeight());
            drawRoundRect(canvas, sliderHeight, sliderHeight);
            left += sliderWidth + mOptions.getSliderGap();
        }
    }
}
